#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <alsa/asoundlib.h>
#include "aacenc_lib.h"

HANDLE_AACENCODER g_fdk_aac_enc_phandle = NULL;
//init_fdk_encoder(16000,1);
int  init_fdk_encoder(int sample_rate, int channels)
{
  	int ret = 0;

	//int  sample_rate, channels, bits_per_sample;
	
	int bitrate;
	int aot = 2;
	int afterburner = 1;
	int eld_sbr = 0;
	int vbr = 0;

	//CHANNEL_MODE mode;
	AACENC_InfoStruct info = { 0 };
	
    printf("\r\n%s =====>>\n",__FUNCTION__);
	//sample_rate = 16000;
	//channels = 1;
	int mode = 1; //MODE_2
	bitrate = 24000;//32000; 
	
	if (aacEncOpen(&g_fdk_aac_enc_phandle, 0, channels) != AACENC_OK) {
		fprintf(stderr, "Unable to open encoder\n");
		return 1;
	}
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_AOT, aot) != AACENC_OK) {
		fprintf(stderr, "Unable to set the AOT\n");
		return 1;
	}
	if (aot == 39 && eld_sbr) {
		if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_SBR_MODE, 1) != AACENC_OK) {
			fprintf(stderr, "Unable to set SBR mode for ELD\n");
			return 1;
		}
	}
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) {
		fprintf(stderr, "Unable to set the AOT\n");
		return 1;
	}
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_CHANNELMODE, mode) != AACENC_OK) {
		fprintf(stderr, "Unable to set the channel mode\n");
		return 1;
	}
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_CHANNELORDER, 1) != AACENC_OK) {
		fprintf(stderr, "Unable to set the wav channel order\n");
		return 1;
	}
	if (vbr) {
		if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_BITRATEMODE, vbr) != AACENC_OK) {
			fprintf(stderr, "Unable to set the VBR bitrate mode\n");
			return 1;
		}
	} else {
		if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_BITRATEMODE, 0) != AACENC_OK) {
			fprintf(stderr, "Unable to set the CBR bitrate mode\n");
			return 1;
		}
		if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_BITRATE, bitrate) != AACENC_OK) {
			fprintf(stderr, "Unable to set the bitrate\n");
			return 1;
		}
	}
	
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_TRANSMUX, 2) != AACENC_OK) {
		fprintf(stderr, "Unable to set the ADTS transmux\n");
		return 1;
	}
	if (aacEncoder_SetParam(g_fdk_aac_enc_phandle, AACENC_AFTERBURNER, afterburner) != AACENC_OK) {
		fprintf(stderr, "Unable to set the afterburner mode\n");
		return 1;
	}
	if ((ret = aacEncEncode(g_fdk_aac_enc_phandle, NULL, NULL, NULL, NULL)) != AACENC_OK) {
		fprintf(stderr, "Unable to initialize the encoder [%d]\n",ret);
		return 1;
	}
	if (aacEncInfo(g_fdk_aac_enc_phandle, &info) != AACENC_OK) {
		fprintf(stderr, "Unable to get the encoder info\n");
		return 1;
	}
	
    printf("> fdk encode info: channels = %d\tframe_size = %d\n",   \
            info.inputChannels, info.frameLength);
	 printf("\r\n%s <<<=====\n",__FUNCTION__);
     return 0;
}

int fdk_encode_audio(INT_PCM *output_buf, int *output_size, unsigned char *buffer, int size)
{
	int ret = 0;
    
	AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
	AACENC_InArgs in_args = { 0 };
	AACENC_OutArgs out_args = { 0 };
	int in_identifier = IN_AUDIO_DATA;
	int in_size, in_elem_size;
	int out_identifier = OUT_BITSTREAM_DATA;
	int out_size, out_elem_size;

	void *in_ptr, *out_ptr;

	AACENC_ERROR err;

    //printf("\r\n%d %s =====>>\n",__LINE__,__FUNCTION__);
	
	in_ptr = buffer;
	in_size = size;
	in_elem_size = 2;

	in_args.numInSamples = size/2;
	in_buf.numBufs = 1;
	in_buf.bufs = &in_ptr;
	in_buf.bufferIdentifiers = &in_identifier;
	in_buf.bufSizes = &in_size;
	in_buf.bufElSizes = &in_elem_size;
		
	out_ptr = output_buf;
	out_size = *output_size;
	out_elem_size = 1;
	out_buf.numBufs = 1;
	out_buf.bufs = &out_ptr;
	out_buf.bufferIdentifiers = &out_identifier;
	out_buf.bufSizes = &out_size;
	out_buf.bufElSizes = &out_elem_size;
	//printf("\r\n%d %s =====>>\n",__LINE__,__FUNCTION__);
	if ((err = aacEncEncode(g_fdk_aac_enc_phandle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) {
		printf("-------------------------------err=%d\n",err);
		if (err != AACENC_ENCODE_EOF){
			fprintf(stderr, "%s Encoding failed\n",__FUNCTION__);
			return -1;
		}
	}
    if(out_args.numOutBytes > 352){
	  printf("\r\n%s <<=====[%d]\n",__FUNCTION__,out_args.numOutBytes);	
    }
    return out_args.numOutBytes;
}

int aac_init()
{
	init_fdk_encoder(16000,1);	
}

#define RATE    16000 //采样频率
#define SIZE    16   //量化位数
#define CHANNELS 1   //声道数目
#define RSIZE    2048    //buf的大小


 int rc;
int size;
FILE *fp ;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val,val2;
int dir;
snd_pcm_uframes_t frames;
char *buffer;

int aac_stream_init()
{
    /* Open PCM device for recording (capture). */
    rc = snd_pcm_open(&handle, "default",SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0)
    {
        fprintf(stderr,  "unable to open pcm device: %s/n",  snd_strerror(rc));
        exit(1);
    }
    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&params);
    /* Fill it in with default values. */
    snd_pcm_hw_params_any(handle, params);
    /* Set the desired hardware parameters. */
    /* Interleaved mode */
    snd_pcm_hw_params_set_access(handle, params,
                                 SND_PCM_ACCESS_RW_INTERLEAVED);
    /* Signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(handle, params,
                                 SND_PCM_FORMAT_S16_LE);
    /* Two channels (stereo) */
    snd_pcm_hw_params_set_channels(handle, params, 1);
    /* 44100 bits/second sampling rate (CD quality) */
    val = RATE;
    snd_pcm_hw_params_set_rate_near(handle, params,  &val, &dir);
    /* Set period size to 32 frames. */
    frames = RSIZE/(SIZE/8);
    snd_pcm_hw_params_set_period_size_near(handle,  params, &frames, &dir);
    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr,  "unable to set hw parameters: %s/n",
                snd_strerror(rc));
        exit(1);
    }
    /* Use a buffer large enough to hold one period */
    snd_pcm_hw_params_get_period_size(params,  &frames, &dir);
    size = frames * SIZE /8; /* 2 bytes/sample, 2 channels */
    printf("size = %d\n",size);
    buffer = (char *) malloc(size);
    /* We want to loop for 5 seconds */
    snd_pcm_hw_params_get_period_time(params,  &val, &dir);

	
	aac_init();
	
	
}

int aac_stream_deinit()
{
	snd_pcm_drain(handle);
	snd_pcm_close(handle);
	free(buffer);
}

int aac_stream_get(char *pAacBuf, int aacBufLen)
{
	int rtv = 0;
	int x = 0;
	struct  timeval    tv;
	
	rc = snd_pcm_readi(handle, buffer, frames);
		
        gettimeofday(&tv,0);
        if (rc == -EPIPE)
        {
            /* EPIPE means overrun */
            fprintf(stderr, "overrun occurred/n");
            snd_pcm_prepare(handle);
        }
        else if (rc < 0)
        {
            fprintf(stderr,
                    "error from read: %s/n",
                    snd_strerror(rc));
        }
        else if (rc != (int)frames)
        {
            fprintf(stderr, "short read, read %d frames/n", rc);
        }

	rtv = fdk_encode_audio((INT_PCM *)pAacBuf, &aacBufLen, (unsigned char*)buffer, frames*2);
	//printf("tv_sec:%d tv_usec:%-6d .aac rtv = %d rc = %d\n", (int)tv.tv_sec ,(int)tv.tv_usec,rtv,rc);

	return rtv;
}





